import datetime
from app.db.models.alert_groups import AlertGroup
from app.db.models.jobs import Job


class RefreshAlertGroupInfo:
    default_settings = {
        "enable": {
            "asset": True,
            "vul": True,
            "ssl": True,
            "cyd": True,
            "securityEvent": True,
            "http": True,
            "ping": True,
            "hostVul": True,
            "content": True,
        },
        "notification": {
            "email": True,
            "sms": True,
            "wechat": True,
            "inBox": True
        },
        "smsAllowedTime": {
            "start": "00:00:00",
            "end": "23:59:59"
        },
        "emailAllowedTime": {
            "start": "00:00:00",
            "end": "23:59:59"
        },
        "smsDailyLimit": 10,
        "emailDailyLimit": 10,
    }

    def get_setting_str(self, key_list, setting):
        result = ""
        for key in key_list:
            result += "{}:{}".format(key, setting.get(key, False))
        return result

    def job_alert_setting_maps(self):
        jobs = Job.objects.find()
        alert_setting_maps = dict()
        for job in jobs:
            alert_settings = job.alertSettings
            alert_group_ids = alert_settings.alertGroupIds
            if not alert_group_ids:
                continue

            enable_keys = ["asset", "vul", "ssl", "cyd", "securityEvent", "http", "ping", "hostVul", "content"]
            enable = alert_settings.enable
            enable_str = self.get_setting_str(enable_keys, enable)

            notification_keys = ["email", "sms", "wechat", "inBox"]
            notification = alert_settings.notification
            notification_str = self.get_setting_str(notification_keys, notification)

            allowed_time_keys = ["start", "end"]
            sms_allowed_time = alert_settings.smsAllowedTime
            sms_allowed_time_str = self.get_setting_str(allowed_time_keys, sms_allowed_time)

            email_allowed_time = alert_settings.emailAllowedTime
            email_allowed_time_str = self.get_setting_str(allowed_time_keys, email_allowed_time)

            daily_limit_str = "{}:{}".format(alert_settings.smsDailyLimit, alert_settings.emailDailyLimit)

            setting_str = enable_str + notification_str + sms_allowed_time_str + email_allowed_time_str + daily_limit_str
            for alert_group_id in alert_group_ids:
                if alert_group_id not in alert_setting_maps:
                    alert_setting_maps[alert_group_id] = {
                        "key": {setting_str},
                        "settings": alert_settings.to_dict(),
                        "default": False
                    }
                else:
                    if setting_str not in alert_setting_maps[alert_group_id]["key"]:
                        alert_setting_maps[alert_group_id]["key"].add(setting_str)
                        alert_setting_maps[alert_group_id]["settings"] = {}
                        alert_setting_maps[alert_group_id]["default"] = True
        return alert_setting_maps

    def alert_group_alert_settings(self, alert_setting_maps):
        alert_groups = AlertGroup.objects.filter()
        default_setting_ids = []
        not_default_setting_maps = dict()
        for alert_group in alert_groups:
            alert_group_id = alert_group.id
            alert_setting = alert_setting_maps.get(str(alert_group_id), {})
            if not alert_setting:
                default_setting_ids.append(alert_group_id)
                continue

            if alert_setting['default']:
                default_setting_ids.append(alert_group_id)
                continue

            not_default_setting_maps[alert_group_id] = alert_setting['settings']
        return default_setting_ids, not_default_setting_maps

    def set_alert_group_default_alert_settings(self, default_setting_ids):
        AlertGroup.objects(pk__in=default_setting_ids).update(alertSettings=self.default_settings)

    def set_alert_group_alert_settings(self, alert_group_id, alert_settings):
        AlertGroup.objects(pk=alert_group_id).update(alertSettings=alert_settings)

    def job_deafault_alert_group_maps(self):
        alert_group_maps = dict()
        uid_set = set()
        jobs = Job.objects.find({"$where": "this.alertSettings.alertGroupIds.length > 1"})
        for job in jobs:
            uid = job.uid
            uid_set.add(uid)
            if uid not in alert_group_maps:
                alert_group_maps[uid] = [job.id]
            else:
                alert_group_maps[uid].append(job.id)
        return list(uid_set), alert_group_maps

    def alert_group_default_maps(self, uid_list):
        alert_group_maps = dict()
        alert_groups = AlertGroup.objects.filter(uid__in=uid_list, isDefault=True)
        for alert_group in alert_groups:
            alert_group_maps[alert_group.uid] = str(alert_group.id)
        return alert_group_maps

    def set_job_default_alert_group_id(self, job_maps, alert_group_maps):
        for uid, job_ids in job_maps.items():
            default_alert_group_id = alert_group_maps.get(uid, '')
            if default_alert_group_id:
                Job.objects(pk__in=job_ids).update(alertSettings__alertGroupIds=[str(default_alert_group_id)])

    def update_alert_group_name(self):
        AlertGroup.objects(isDefault=True).update(name="默认告警策略")

    def service(self):
        print(f"{datetime.datetime.now()} 开始同步告警数据......")
        self.update_alert_group_name()

        alert_setting_maps = self.job_alert_setting_maps()
        default_setting_ids, not_default_setting_maps = self.alert_group_alert_settings(alert_setting_maps)
        self.set_alert_group_default_alert_settings(default_setting_ids)
        for alert_group_id, alert_settings in not_default_setting_maps.items():
            if "alertGroupIds" in alert_settings:
                del alert_settings["alertGroupIds"]
            self.set_alert_group_alert_settings(alert_group_id, alert_settings)

        uid_list, job_maps = self.job_deafault_alert_group_maps()
        alert_group_maps = self.alert_group_default_maps(uid_list)
        self.set_job_default_alert_group_id(job_maps, alert_group_maps)
        print(f"{datetime.datetime.now()} 告警数据同步完成")
